package com.qianli.cashmama.trade.common.encryption;


import com.alibaba.fastjson.JSONObject;
import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.sql.Timestamp;
import java.util.*;

/**
 * @Author: cashmama
 * @Date: 2020/11/6-15:43
 * @Description: TODO
 * @Slogan: To be or not to be
 **/
public class StandardUtil {
    private static final String CHARSET = "UTF-8";
    private static final Integer DES_KEY_LEN = 16;
    private static final String ALL_CHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final String DES_ALGORITHM_NAME = "DES";
    private static final String RSA_ALGORITHM_NAME = "RSA";
    private static final String DES_ALGORITHM_CIPHER = "DES/ECB/PKCS5Padding";
    private static final String RSA_ALGORITHM_CIPHER = "RSA/ECB/PKCS1Padding";
    private static final String RSA_ALGORITHM_TYPE = "SHA1WithRSA";
    /**样例----我司平台公钥*/
//    private static final String JSXM_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDstVyj0YYfL3DiGjO+0ZE4+zM7g/z9N8NtAWi5aWzh6Jej1EKWwibzedWnJc1nSg9d43DoommnccgKmaCOYFm0NsgsyUX9923ebp6tLSMVNfYigsr13P//nbcVpQ9cu/TtLejcVUjmV5vuG4Vz+JZK/sfapP/TjZwtD0Huq+y2wQIDAQAB";
    private static final String JSXM_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkRHFhZ2OZM17YFrE/4X/HgamSw4bIOdY8OCpzlqyDC06ICMh4AnlBoBu7pDTzBP0BcefBDCic4tf+X1yx3nrTTrddaVLJ0WTdae7ZOEdgY8MAa/w/iD78rD0Gp42lN1Vf46GQlHLbQeb7Kr1LViKt3YF+SBre2DV8Dp6063KmVwIDAQAB";
    /**样例----我司平台私钥*/
    private static final String JSXM_PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIAD8W+lGvF3yDtLYZgYQizZBA8kZzhMhou6Iy/dyInWWpltVhTMyOwLqhCDIeL6susWbDykUnHRimgywrXjxW0FVH06tUiE7GIeRei5Bmd4Ce6DXxB2hEanm+6BVjVdGg8IK565tQkFcaWmQaTEmqc1FlMKkUyHBHl5JIfDyjLPAgMBAAECgYBN8hivwfgFzsk8UUm7MgoZBIpULfYrcWz65vtFyeSxCLNheBFR2N792pxSMYYQjlUijySYR/VrGAsOJtonpegu/NrK6sUfNY2fYZ1fUWupeoMg79cmNmO/55ZBy8QdMZka8zfss3nQaEY5iluCKr8hoZ6pSZKBTvnEOFTMNV5kAQJBALtQkGfi5seFfa2kBiNshgqNRC0Yq0kq0YWk7/JyVMWkkTtkjRCvdXGKU/uNf7mSz312zzbhVUF/Z2bxUq07u18CQQCu9OOMts79XvT4jpTjiri9eGIoVxZ2kzUCNSNK5n0XNpdh54F4vHelAMN/dQocD8UH5ANCxxgb4IILeFyk9i6RAkAWlFOT8koXawQHVmpXAtH1m6nINd0P6NVw4rz54MZPPNM08Z3/kOb7VM1i2V+4IvZYDWZVGzyHtK/mPNjWgQjJAkEArI0iD5oMs59/g9U7yt76LQQZ6ydZJEEzOqYl1K1WGhrhWtH0w5s9dSM3rPFFsz9qV8nt3WJ2yKe4Go/u71NNwQJBAI/Us9XsbPoeQe+dkRhsix8ol+VvjKCbw9Ke13YC2ioT7oEVU8FZirXHV8zEzj5BhD6TP0qVUUxhVWukC64lsH0=";
    /**样例----合作机构公钥*/
    private static final String CO_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt7VzZd7zB9UpNBtAe7x6HWFK07Xr8RtQUSAN1XT6g+f9sc5FRMWXO0d7ApLt3+HUPPwbgLF23PMcrCTxbS+wuEzET5jVuanPwfcc66Z5aFZ8acxHj7a5xPrDQMlxPIAizcy75e8At66TqElO5MPgjc3LDQCRgnKhUday4TjLimQIDAQAB";
    /**样例----合作机构私钥*/
    private static final String CO_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKDXZ/pMBX/y8KSLYt3MuaxmpwqCcfGZaSwU+TzzesYW6gQg5EEAS5qBMffiodKrjUV7fW3uSkwuOKaSxaHUA1yy5YA99zV2jz6Lv3lRhvhu8trqO8ZtWYeMwdLyr1Ie+uJtTd52UNOJZm4Nvqok5yZnfeM1zZkwf/S3fFZtv1LBAgMBAAECgYB0hfm/PIoTevZZzt1uYJ33R1sm4wAXjxPBquQyAxbkIb+iBA45BTTAl26S7m5cCIrNVry1Aphy/l1uWBCzv7w6qYbQtwVSNOv1J2WFzakaLdEL+P5ZMauKTS/b/mhHiZlSRzFbfLx7ge/hsLR1OSQxy9cIOvcDD7kvrx+5GX3H0QJBAOE3h3LEFIAAPXoPhq3zAg5Ie9dZAScQHmsqwXWHkIJWEacT+Fgxuj0lvFalC1VVy7wQsXD5EYtfMPhOnyZUhJ0CQQC201dtV+1Na6j/H/fMSXmKVSNWUI2epQH4Y9sAsu/FsVotehBQV2Y3QTVcEu3wQEAMwuMGtOPq1SRCZeR6TmN1AkEAycXxIN4RK7iLW37rf462qctAwGdqQ/AKAKNWnZBt5Idt201l8sXigAP933aQV8y88enWv0s177LB8cSmizWvdQJBAIWB28w7c00gG28C9z+1QA4mkgGMHX8GXGP494qRIMsq8gFXq+YfjMM42TB9mkfhg2RORN825WEteKcMJUazS6kCQQDWppJxUmMjldUsE7MRLI8wEnGMIjEc/SFNhQ08HFmBi5R9M3X/RTFJsEQZxJidHMqfdJJM6RwHuY6mV9OYZWAL";

    private static String ORCA_PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAN6+KRPIva0cc9k48Dbv3HoQoN3v68iC3E4NHN+2L6mAYkrNfuhA1XCUGt7uV4ZyREyzIHWmTfBn8mtc1XPLyS/zhGsAmxmH5j8TYTAU5Ifgg1wRvAfFKMELYQtcHZ1cLTWXUYYepESTVvigEAuhPtu6COLz24Fj807QbZ18ebUdAgMBAAECgYBkSxFp5BhrywTqyTV4NxZ6K+STKgVrmmiiCEt4+6qIUtNvRQogf5jbgQR8XqswUWEpe/pgnwo29kb0Sq+d3SNvyZgyjfpheUHPN2ekBqSaKN/E3oGcOHtiCQhPbqG9PusQ7RJ6k4pfwGmLV5Z60hDmiUbehg7B5n6iEfPo5LaFLQJBAPplvjX8tB7mJoyYP8U2fmmhnh8uEuVOxdrvnYIC3LUiul6kVN9FFGma2eKswEb+gZMu7f/KLjUluLgey8W+wqMCQQDjugORtY4pSU+3jw2hoU/egBy22wEhwK3zApkOOW32W0+FybYRB1kWG9QNhfmH50BbxqfvPePyGORQsphqpOU/AkAe1UR01WdAnsqEaYMAv9MVIsebw0qkXezTJspYZg3TaDFW0hl5XMJEtsK5vNf4ZgKCoza/VqAV/00drv0cnn7NAkAqy544F8Jrh9dvS3boVQRJcBH1WxrPWQJXlLlmruw3S9mZ7tpEQPlA6mHjWLYYECFMHf0ZPKxFpt/hOm7iO7LJAkEAvF+mL37RX3/LLIV77DdAz5FcnFefrxD5AxHcpcJRCnkZFd98qmD4xcZEt8fzGiVpesxGzsXq9WMmKjh3JEj7XA==";
    private static String ORCA_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDevikTyL2tHHPZOPA279x6EKDd7+vIgtxODRzfti+pgGJKzX7oQNVwlBre7leGckRMsyB1pk3wZ/JrXNVzy8kv84RrAJsZh+Y/E2EwFOSH4INcEbwHxSjBC2ELXB2dXC01l1GGHqREk1b4oBALoT7bugji89uBY/NO0G2dfHm1HQIDAQAB";

    private static final String SELF_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt7VzZd7zB9UpNBtAe7x6HWFK07Xr8RtQUSAN1XT6g+f9sc5FRMWXO0d7ApLt3+HUPPwbgLF23PMcrCTxbS+wuEzET5jVuanPwfcc66Z5aFZ8acxHj7a5xPrDQMlxPIAizcy75e8At66TqElO5MPgjc3LDQCRgnKhUday4TjLimQIDAQAB";
    private static final String SELF_PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK3tXNl3vMH1Sk0G\n" +
            "0B7vHodYUrTtevxG1BRIA3VdPqD5/2xzkVExZc7R3sCku3f4dQ8/BuAsXbc8xysJ\n" +
            "PFtL7C4TMRPmNW5qc/B9xzrpnloVnxpzEePtrnE+sNAyXE8gCLNzLvl7wC3rpOoS\n" +
            "U7kw+CNzcsNAJGCcqFR1rLhOMuKZAgMBAAECgYEAmUev5WO18YWYNqwDbM+1qvf2\n" +
            "48bK9VwCeeFBUwSbNkk8hrqO3exX2d5xnntPUBqiJ46XI6dV7C/fIxlfnOIbQMeN\n" +
            "wjmnPi3CzbOXf+NML6MH+JhhvzgmS2w92faVvCdcEeAt11hNLRC/+2H37PSZvhhG\n" +
            "TdXYHwG9psORZv3qxGUCQQDc5nY1CNXESmtrZH5NukW1rWwY1daTJEaIBTx4RyzY\n" +
            "6sfwb2PAMZqqfxfcEYlZ6BwisteglyzMrBZ7byGVeB63AkEAyZAu0tTc4qIMCRg1\n" +
            "eLYAQ6HCIxFf7LQXDJlnSTxlnSTEVPxIpha0avHYvtcnjb1HF7ZXcbrg6P6FxHvw\n" +
            "1aW5LwJAJeLA00e4ofnBgqGxp9MSsZ4UtA24x3OpRRrgzCAo6Osbb3krOoNHa4Zw\n" +
            "qSW40NqmOK1Dnh9PZ6r8EB93OxNm8QJAEksftMrU8Uy7wueLktUR2RGJSR1+k0EV\n" +
            "BnO1yBPPNR/tIblz7n8JCNvCTC/Cyz5ugVxvO0c2um6/PUHybbGIyQJAX5RRR8wMzF2EDkKkPV2DsiM25QvjTe+NCERamguMzQXrfN+WPqXMR4XsdUDX66kgvh9IHOmljly791CCKQWihw==";

    /**本工具类使用demo*/
    public static void main(String[] args) throws Exception {
//        //样例--合作机构需要发送的业务报文
//        String bizData = "{\"order_no\":\"1679042695362711552\",\"repayment_plan\":[{\"due_time\":1564070399000,\"amount\":\"1407.92\",\"paid_amount\":\"600.00\",\"period_no\":\"1\",\"pay_type\":1,\"remark\":\"\",\"billitem\":[{\"feename\":\"本金\",\"dueamount\":\"2000.00\",\"feetype\":1},{\"feename\":\"利息\",\"dueamount\":\"7.92\",\"feetype\":2},{\"feename\":\"罚息\",\"dueamount\":\"0.00\",\"feetype\":3}],\"can_repay_time\":1563520061000,\"success_time\":1563522247000,\"overdue_fee\":\"0\",\"bill_status\":\"1\"}],\"bank_card\":\"6214832147457027\",\"open_bank\":\"CMBCHINA\"}";
//        //组装发送给我司平台的数据对象
//        SendData sendData = StandardUtil.assemblySendData(bizData, StandardUtil.JSXM_PUBLIC_KEY, StandardUtil.CO_PRIVATE_KEY, "P1000001", "api.payment.plan");
//        System.out.println("SendData：" + JSONObject.toJSONString(sendData));
//
//        //样例--接收到我司平台发送的完整原始报文
//        String receiveStr = "{\"method\":\"fund.cert.auth\",\"sign\":\"VbnUa7ci3t8bTQPtdMl1Fdoi5oE5na8wpl0EYShheEcFf1MY3nnPakz8LYhT9Zek/29nq8QjTFcM99SoO08Ifa2wAOHYM7Xt/jVK+QMYw2a/V1n9oPRNEneb52RW9+hvv8t4AmpWnwAntoOIPVp+qdxBelI0dli06wUQo97VnCM=\",\"merchant_id\":\"20190418\",\"des_key\":\"RJeecDAZes2sENROoFJOXEJzBmEaDCmnZ6WbLWjhO5ZULllqFlMuGGE+XRg6muF+ECGYypayppwoh05UJP7zsglx1jQEvsttyUNT5k9/ljeSJ4ReYI103XyHvDcDdboJ7jomHMi03kqNk5SShLFlNnlZCoJmfb6yFmsGnRb49xQ=\",\"biz_data\":\"qSrLMHgcY3N3Qk4XW59vmV0BcYejrBCAC6CvotLeYTvTmqVMWLo0le9rGEa0Y4AECV2/KwWU0jHgLpF8AGOXT+xj0+DgX/giZTNnK18nVZUJw4nz6h3lvz3oK5xpqZBWHFAotJk9jcbK2hm3CuImaeneCiAxqM9OYOp/j2Yi+t9zBzgMpgvKgPyg3iOh0LB7bPBpAjvDiisnm0XE+BOlyeV9D7R/ofl1CkZPuyzfQ8jFn0iIfIDD5P7pmIN/WA0K\",\"biz_enc\":\"1\"}";
//        //转换成对象
//        ReceiveData receiveData = JSONObject.parseObject(receiveStr, ReceiveData.class);
//        try {
//            //从我司平台发送的请求中提取业务报文
//            String content = StandardUtil.getBizData(receiveData, JSXM_PUBLIC_KEY,CO_PRIVATE_KEY);
//            System.out.println("ReceiveData：" + content);
//        } catch (SignatureException e) {
//            e.printStackTrace();
//        }


//        ReceiveData receiveData = new ReceiveData();
//        String bizData = "{\"applyDetail\": {\"birthday\": \"1983-10-16\",\"colleague_name\": \"Krishna Nuli\",\"company_address\": \"S/O M K Mahammad Hussen, 12-1111, Lalugarden, Lalugarden\",\"company_city\": \"Chittoor\",\"company_industry\": 1,\"company_name\": \"Lucky Company\",\"company_pin_code\": \"110018\",\"company_tel\": \"12132132132\",\"contact_mobile\": \"+918123456789\",\"contact_name\": \"Shaaly Chopra\",\"contact_relationship\": 1,\"current_address\": \"S/O M K Mahammad Hussen, 15-1714, Lalugarden, Lalugarden\",\"current_city\": \"Chitoor\",\"current_pin_code\": \"110018\",\"email\": \"gaurav.chopra@gmail.com\",\"employee_type\": 1,\"face_image_array\": [\"https://finance-glb.s3.ap-south-1.amazonaws.com/upload/dev/i/202009/16003153573637944.jpg\"],\"gender\": 1,\"idcard_address\": \"S/O: Vijay Chopra, H NO-115 HIMGIRI APARTMENTS, Vikas Puri, Tilak Nagar, West Delhi, Rajouri Garden, Delhi, 110018\",\"idcard_image_back\": \"https://finance-glb.s3.ap-south-1.amazonaws.com/upload/dev/i/202009/16001531267967393.jpg\",\"idcard_image_front\": \"https://finance-glb.s3.ap-south-1.amazonaws.com/upload/dev/i/202009/16002409815038325.jpg\",\"idcard_pin_code\": \"110018\", \"language\": 1,\"loan_purpose\": 1,\"marital_status\": 2,\"monthly_income\": 3,\"occupation\": 3,\"pancard_image\": \"https://finance-glb.s3.ap-south-1.amazonaws.com/upload/dev/i/202009/16001548281880490.jpg\",\"religion\": 3,\"residence_type\": 2,\"user_education\": 4,\"working_since\": \"2005-08-01\"},\"orderInfo\": {\"idcard_no\": \"854629568912\",\"is_reloan\": 0,\"order_no\": \"1584550783723470822\",\"order_time\": \"1600345990179\",\"pancard_no\": \"AHQPC3868H\",\"user_mobile\": \"917123456789\",\"user_name\": \"Gaurav Chopra\"}}";
//        String desKey = generateDesKey();
//        String desEncryptedData = desEncrypt(bizData, desKey);
//        receiveData.setBiz_data(desEncryptedData);
//        receiveData.setMethod("fund.userinfo.base");
//        receiveData.setMerchant_id("T100011");
//        receiveData.setDes_key(rsaEncrypt(desKey,ORCA_PUBLIC_KEY));
//        receiveData.setBiz_enc("1");
//        String toSign = getSignParamStr(JSONObject.toJSONString(receiveData));
//        String sign = sign(toSign, SELF_PRIVATE_KEY);
//        receiveData.setSign(sign);
//        System.out.println("ReceiveData：" + JSONObject.toJSONString(receiveData));

        String a = "{\"biz_data\":\"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\",\"biz_enc\":\"1\",\"des_key\":\"dd2lnktS+58dQ6pJjwi2twZs2n2tEYcJtWy+tT4UllGitgfbOyZK0Z0+GfTH2LMTnz7S4G+5IveuGsOJOfTzX0KOVYviq9GfVE75UomuPrrT/j2O8JKOB6oIvjX5u7YKcv6Src0vMlQ93VwNNQp9xQnKC/0FbauDJ1esZeCeoRg=\",\"merchant_id\":\"T100011\",\"method\":\"fund.userinfo.base\",\"sign\":\"j3YgbRWkNSBy0YAF7kEhX+e2t6f//ybpBfuvSn9LYYQn+31VBIuslnJSWQq+MtuHWe8NztiEoH7KKlk+mV31QeGXeHrXdXVjwk/yMyBbXn8NsZLhuFROdvnyssDWjbGMjdm2E/wCOPUVsh30EKrWsztGOHCwNqagoKg63RUSqm0=\"}";
        JSONObject jsonRet = JSONObject.parseObject(a);
        String bizEnc = jsonRet.getString("biz_enc");
        if (bizEnc.equals("1")) {
            String as = jsonRet.getString("sign");
            String jsonDataSorted = StandardUtil.getSignParamStr(a);
            System.out.println( StandardUtil.checkSign(jsonDataSorted, as, SELF_PUBLIC_KEY));
        }
    }

    /**
     * 生成DES秘钥，长度为16位
     * @return DES秘钥
     */
    public static String generateDesKey() {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < DES_KEY_LEN; i++) {
            sb.append(ALL_CHAR.charAt(random.nextInt(ALL_CHAR.length())));
        }
        return sb.toString();
    }

    /**
     * DES 算法 ECB 模式 PKCS5 填充方式加密
     * @param source 待加密字符串
     * @param key DES秘钥
     * @return 加密后并base64的字符串
     */
    public static String desEncrypt(String source, String key) throws Exception {
        SecureRandom random = new SecureRandom();
        DESKeySpec desKey = new DESKeySpec(key.getBytes());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM_NAME);
        SecretKey secureKey = keyFactory.generateSecret(desKey);

        Cipher cipher = Cipher.getInstance(DES_ALGORITHM_CIPHER);
        cipher.init(1, secureKey,random);

        byte[] buf = cipher.doFinal(source.getBytes());

        return new String(Base64.encodeBase64(buf));
    }

    /**
     * DES 算法 ECB 模式 PKCS5 填充方式解密
     * @param cryptoGraph 加密后的密文
     * @param key DES秘钥
     * @return 解密后的内容
     */
    public static String desDecrypt(String cryptoGraph, String key) throws Exception {
        try {
            SecureRandom random = new SecureRandom();
            DESKeySpec desKey = new DESKeySpec(key.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES_ALGORITHM_NAME);
            SecretKey secureKey = keyFactory.generateSecret(desKey);

            Cipher cipher = Cipher.getInstance(DES_ALGORITHM_CIPHER);
            cipher.init(2, secureKey,random);
            byte[] buf = cipher.doFinal(Base64.decodeBase64(cryptoGraph.getBytes()));
            return new String(buf);
        } catch (Exception e) {
            throw e;
        }
    }


    /**
     * 签名方法（RSA签名）
     * RSA签名规则：加签用私钥，验签用公钥
     * @param content 待签名内容
     * @param privateKey RSA私钥
     * @return 签名串
     */
    public static String sign(String content, String privateKey) throws Exception {
        try {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey.getBytes()));
            KeyFactory keyf = KeyFactory.getInstance(RSA_ALGORITHM_NAME);
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);
            Signature signature = Signature.getInstance(RSA_ALGORITHM_TYPE);
            signature.initSign(priKey);
            signature.update(content.getBytes(CHARSET));
            byte[] signed = signature.sign();
            return new String(Base64.encodeBase64(signed));
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * 验签方法（RSA签名）
     * RSA签名规则：加签用私钥，验签用公钥
     * @param content 待验签内容
     * @param sign 签名串
     * @param publicKey RSA公钥
     * @return 验签是否通过
     */
    public static boolean checkSign(String content, String sign, String publicKey) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM_NAME);
            byte[] encodedKey = Base64.decodeBase64(publicKey.getBytes());
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
            Signature signature = Signature.getInstance(RSA_ALGORITHM_TYPE);
            signature.initVerify(pubKey);
            signature.update(content.getBytes(CHARSET));
            return signature.verify(Base64.decodeBase64(sign.getBytes()));
        } catch (Exception var8) {
            var8.printStackTrace();
            return false;
        }
    }

    /**
     * 把json字符串中的所有的参数按照参数名做字典序排序
     * @param json 待排序json字符串
     * @return 排序后字符串
     */
    public static String getSignParamStr(String json){
        Map<String,Object> paramMap = JSONObject.parseObject(json);

        Collection<String> keySet = new LinkedHashSet<>();
        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
            if( entry.getValue() != null && !"".equals(entry.getValue()) && !"sign".equals(entry.getKey())){
                keySet.add(entry.getKey());
            }
        }
        //按照参数名做字典序排序
        List<String> list= new ArrayList<>(keySet);
        Collections.sort(list);
        //拼接参数
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<list.size();i++){
            if(i < list.size()-1){
                sb.append(list.get(i)).append("=").append(paramMap.get(list.get(i))).append("&");
            }else{
                sb.append(list.get(i)).append("=").append(paramMap.get(list.get(i)));
            }
        }
        return sb.toString();
    }

    /**
     * 根据公钥字符串获取公钥对象
     * @param key 公钥字符串
     * @return PublicKey公钥对象
     */
    public static PublicKey getPublicKey(String key) throws Exception {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(key.getBytes()));
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM_NAME);
        return keyFactory.generatePublic(keySpec);
    }
    /**
     * 根据私钥字符串获取私钥对象
     * @param key 私钥字符串
     * @return PrivateKey私钥对象
     */
    public static PrivateKey getPrivateKey(String key) throws Exception {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(key.getBytes()));
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM_NAME);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     *  RSA加密方法
     *  RSA加解密规则：加密用公钥，解密用私钥
     * @param source 待加密内容
     * @param publicKey RSA公钥
     * @return 加密后并Base64后的字符串
     */
    public static String rsaEncrypt(String source, String publicKey) throws Exception {
        Key key = getPublicKey(publicKey);
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM_CIPHER);
        cipher.init(1, key);
        byte[] data = source.getBytes(CHARSET);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;

        for(int i = 0; inputLen - offSet > 0; offSet = i * 117) {
            byte[] cache;
            if (inputLen - offSet > 117) {
                cache = cipher.doFinal(data, offSet, 117);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }

            out.write(cache, 0, cache.length);
            ++i;
        }

        return new String(Base64.encodeBase64(out.toByteArray()), CHARSET);
    }
    /**
     *  RSA解密方法
     *  RSA加解密规则：加密用公钥，解密用私钥
     * @param cryptograph 待解密内容
     * @param privateKey RSA私钥
     * @return 解密后的字符串
     */
    public static String rsaDecrypt(String cryptograph, String privateKey) throws Exception {
        Key key = getPrivateKey(privateKey);
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM_NAME);
        cipher.init(2, key);
        byte[] encryptedData = Base64.decodeBase64(cryptograph.getBytes());
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;

        for(int i = 0; inputLen - offSet > 0; offSet = i * 128) {
            byte[] cache;
            if (inputLen - offSet > 128) {
                cache = cipher.doFinal(encryptedData, offSet, 128);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            ++i;
        }

        byte[] decryptedData = out.toByteArray();
        return new String(decryptedData, CHARSET);
    }

    /**
     * 填充数据
     */
    public static void fillSendData(SendData sendData){
        sendData.setSign_type("RSA");
        sendData.setBiz_enc("1");
        sendData.setVersion("1.0");
        sendData.setFormat("json");
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        sendData.setTimestamp(Long.toString(timestamp.getTime()));
        sendData.setReturn_url(null);
    }

    /**
     * 获取biz_data业务报文,包含验签和解密操作
     * @param receiveData 接收的数据对象
     * @param jsxmRsaPublicKey 我司平台提供的公钥
     * @param coRsaPrivateKey 合作机构的RSA私钥
     * @return biz_data 我司平台发送的报文业务参数
     * @throws SignatureException 验签错误抛出该异常
     */
    public static String getBizData(ReceiveData receiveData, String jsxmRsaPublicKey, String coRsaPrivateKey) throws SignatureException {
        String sign = receiveData.getSign();
        String jsonData = JSONObject.toJSONString(receiveData);
        String jsonDataSorted = getSignParamStr(jsonData);
        //验签
        boolean signFlag = checkSign(jsonDataSorted, sign, jsxmRsaPublicKey);
        if (signFlag) {
            String encryptDesKey = receiveData.getDes_key();
            try {
                return desDecrypt(receiveData.getBiz_data(), rsaDecrypt(encryptDesKey, coRsaPrivateKey));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            throw new SignatureException("验签失败");
        }
        return null;
    }

    /**
     * 组装发送给我司平台的数据，加密并且做好签名
     * @param bizData 业务报文
     * @param jsxmRsaPublicKey 我司平台提供的公钥
     * @param coPrivateKey 合作机构私钥
     * @param appId 我司平台给合作机构分配的app_id
     * @param method 调用的API方法名称
     * @return 加密加签好的数据对象
     */
    public static SendData assemblySendData(String bizData, String jsxmRsaPublicKey, String coPrivateKey, String appId, String method){
        SendData sendData = new SendData();
        try {
            String desKey = generateDesKey();
            String desEncryptedData = desEncrypt(bizData, desKey);
            sendData.setMethod(method);
            sendData.setDes_key(rsaEncrypt(desKey,jsxmRsaPublicKey));
            sendData.setApp_id(appId);
            sendData.setBiz_data(desEncryptedData);
            fillSendData(sendData);
            String toSign = getSignParamStr(JSONObject.toJSONString(sendData));
            String sign = sign(toSign, coPrivateKey);
            sendData.setSign(sign);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendData;
    }


    public static ReceiveData assemblyReceiverData(String bizData, String jsxmRsaPublicKey, String coPrivateKey, String method, String merchantId) {
        ReceiveData receiveData = new ReceiveData();
        try {
            String desKey = generateDesKey();
            String desEncryptedData = desEncrypt(bizData, desKey);
            receiveData.setBiz_data(desEncryptedData);
            receiveData.setMethod(method);
            receiveData.setMerchant_id(merchantId);
            receiveData.setDes_key(rsaEncrypt(desKey, jsxmRsaPublicKey));
            receiveData.setBiz_enc("1");
            String toSign = getSignParamStr(JSONObject.toJSONString(receiveData));
            String sign = sign(toSign, coPrivateKey);
            receiveData.setSign(sign);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return receiveData;
    }
}
